// Build with:
// g++ two_tasks.cpp -lpthread
#include<future>
#include<thread>
#include<chrono>
#include<random>
#include<iostream>
#include<exception>
using namespace std;
void put_with_delay(char c) {
  // Random number generator
  default_random_engine dre(c);
  uniform_int_distribution<int> id(10, 100);

  // loop to print character after a random period of time
  for(int i=0; i<100; ++i) {
    this_thread::sleep_for(chrono::milliseconds(id(dre)));
    cout.put(c).flush();
  }
}

int main() {
  cout << "Start 2 operations asynchronously..." << endl;

  // Start two threads in the background printing
  // different characters
  auto f1 = async([]{put_with_delay('A');});
  auto f2 = async([]{put_with_delay('B');});

  if(f1.wait_for(chrono::seconds(0)) != future_status::deferred ||
     f2.wait_for(chrono::seconds(0)) != future_status::deferred) {
    while(f1.wait_for(chrono::seconds(0)) != future_status::ready &&
          f2.wait_for(chrono::seconds(0)) != future_status::ready) {
      this_thread::yield();
    }
  }
  cout.put('\n').flush();

  // Wait for all loops to be finished and process any exception
  cout << "Wait for all loops to be finished "
          "and process any exception..." << endl;
  try {
    f1.get();
    f2.get();
  }
  catch(const exception& e) {
    cout << "\nEXCEPTION" << e.what() << endl;
  }
  cout << "\ndone" << endl;
  return 0;
}
